package com.bupt.ilink.tool;

import com.aliyun.bailian20231229.models.*;
import com.aliyun.tea.TeaModel;
import com.bupt.ilink.config.BailianConfig;
import com.bupt.ilink.service.bailian.impl.AddCategoryServiceImpl;
import com.bupt.ilink.service.bailian.impl.ListCategoryServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

@Component
public class BailianFileTools {

    public static String getMd5(MultipartFile file) {
        try {
            //获取文件的byte信息
            byte[] uploadBytes = file.getBytes();
            // 拿到一个MD5转换器
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] digest = md5.digest(uploadBytes);
            //转换为16进制
            return new BigInteger(1, digest).toString(16);
        } catch (Exception e) {
            throw new RuntimeException("获取文件MD5值失败", e);
        }
    }
    public static String getMd5(File file) {
        try (FileInputStream fis = new FileInputStream(file)) {
            // 拿到一个MD5转换器
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            // 创建一个缓冲区来读取文件
            byte[] buffer = new byte[1024];
            int bytesRead;

            // 读取文件内容并更新到 MD5 摘要中
            while ((bytesRead = fis.read(buffer)) != -1) {
                md5.update(buffer, 0, bytesRead);
            }

            // 生成MD5摘要
            byte[] digest = md5.digest();

            // 转换为16进制
            return new BigInteger(1, digest).toString(16);
        } catch (Exception e) {
            throw new RuntimeException("获取文件MD5值失败", e);
        }
    }

    public static String uploadFile(String preSignedUrl, MultipartFile file, String bailianExtra, String contentType){
        HttpURLConnection connection = null;
        try {
            // 创建URL对象
            URL url = new URL(preSignedUrl);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法为PUT，预签名URL默认用于PUT操作进行文件上传
            connection.setRequestMethod("PUT");

            // 允许向connection输出，因为这个连接是用于上传文件的
            connection.setDoOutput(true);

            // 设置请求头，这里设置ApplyFileUploadLease接口返回的Data.Param.Headers中的参数
            connection.setRequestProperty("X-bailian-extra", bailianExtra);
            connection.setRequestProperty("Content-Type", contentType);

            // 读取文件并通过连接上传
            try (DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
                 InputStream fileInputStream = file.getInputStream()) {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }

                outStream.flush();
            }

            // 检查响应代码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 文件上传成功处理
                System.out.println("File uploaded successfully.");
                return "ok";
            } else {
                // 文件上传失败处理
                System.out.println("Failed to upload the file. ResponseCode: " + responseCode);
                return "failed";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "failed";
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    public static String uploadFile(String preSignedUrl, File file, String bailianExtra, String contentType){
        HttpURLConnection connection = null;
        try {
            // 创建URL对象
            URL url = new URL(preSignedUrl);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法为PUT，预签名URL默认用于PUT操作进行文件上传
            connection.setRequestMethod("PUT");

            // 允许向connection输出，因为这个连接是用于上传文件的
            connection.setDoOutput(true);

            // 设置请求头，这里设置ApplyFileUploadLease接口返回的Data.Param.Headers中的参数
            connection.setRequestProperty("X-bailian-extra", bailianExtra);
            connection.setRequestProperty("Content-Type", contentType);

            // 读取文件并通过连接上传
            try (DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
                 InputStream fileInputStream = new FileInputStream(file)) {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }

                outStream.flush();
            }

            // 检查响应代码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 文件上传成功处理
                System.out.println("File uploaded successfully.");
                return "ok";
            } else {
                // 文件上传失败处理
                System.out.println("Failed to upload the file. ResponseCode: " + responseCode);
                return "failed";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "failed";
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    public static List<String> splitPath(String path) {
        // 使用斜杠作为分隔符分割字符串
        String[] parts = path.split("/");


        // 剩余的部分组成 chapterName
        List<String> names = Arrays.asList(parts);


        System.out.println("chapterName: " + names);
        return names;
    }

    public static Boolean checkResponse(TeaModel response) {
        if (response instanceof ListFileResponse listFileResponse) {
            if (!Objects.equals(listFileResponse.getBody().getStatus(), "200") || !listFileResponse.getBody().getSuccess()) {
                System.out.println(listFileResponse.getBody().getCode());
                System.out.println(listFileResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof ListCategoryResponse listCategoryResponse){
            if (!Objects.equals(listCategoryResponse.getBody().getStatus(), "200") || !listCategoryResponse.getBody().getSuccess()) {
                System.out.println(listCategoryResponse.getBody().getCode());
                System.out.println(listCategoryResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DeleteFileResponse deleteFileResponse) {
            if (!Objects.equals(deleteFileResponse.getBody().getStatus(), "200") || !deleteFileResponse.getBody().getSuccess()) {
                System.out.println(deleteFileResponse.getBody().getCode());
                System.out.println(deleteFileResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof AddCategoryResponse addCategoryResponse) {
            if (!Objects.equals(addCategoryResponse.getBody().getStatus(), "200") || !addCategoryResponse.getBody().getSuccess()) {
                System.out.println(addCategoryResponse.getBody().getCode());
                System.out.println(addCategoryResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof AddFileResponse addFileResponse) {
            if (!Objects.equals(addFileResponse.getBody().getStatus(), "200") || !Objects.equals(addFileResponse.getBody().getSuccess(), "true")) {
                System.out.println(addFileResponse.getBody().getCode());
                System.out.println(addFileResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof ApplyFileUploadLeaseResponse applyFileUploadLeaseResponse) {
            if (!Objects.equals(applyFileUploadLeaseResponse.getBody().getStatus(), "200") || !applyFileUploadLeaseResponse.getBody().getSuccess()) {
                System.out.println(applyFileUploadLeaseResponse.getBody().getCode());
                System.out.println(applyFileUploadLeaseResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DeleteFileResponse deleteFileResponse) {
            if (!Objects.equals(deleteFileResponse.getBody().getStatus(), "200") || !deleteFileResponse.getBody().getSuccess()) {
                System.out.println(deleteFileResponse.getBody().getCode());
                System.out.println(deleteFileResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DescribeFileResponse describeFileResponse) {
            if (!Objects.equals(describeFileResponse.getBody().getStatus(), "200") || !describeFileResponse.getBody().getSuccess()) {
                System.out.println(describeFileResponse.getBody().getCode());
                System.out.println(describeFileResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof CreateIndexResponse createIndexResponse) {
            if (!Objects.equals(createIndexResponse.getBody().getStatus(), "200") || !createIndexResponse.getBody().getSuccess()) {
                System.out.println(createIndexResponse.getBody().getCode());
                System.out.println(createIndexResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof GetIndexJobStatusResponse getIndexJobStatusResponse) {
            if (!Objects.equals(getIndexJobStatusResponse.getBody().getStatus(), "200") || !getIndexJobStatusResponse.getBody().getSuccess()) {
                System.out.println(getIndexJobStatusResponse.getBody().getCode());
                System.out.println(getIndexJobStatusResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof SubmitIndexJobResponse submitIndexJobResponse) {
            if (!Objects.equals(submitIndexJobResponse.getBody().getStatus(), "200") || !submitIndexJobResponse.getBody().getSuccess()) {
                System.out.println(submitIndexJobResponse.getBody().getCode());
                System.out.println(submitIndexJobResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof RetrieveResponse retrieveResponse) {
            if (!Objects.equals(retrieveResponse.getBody().getStatus(), "200") || !retrieveResponse.getBody().getSuccess()) {
                System.out.println(retrieveResponse.getBody().getCode());
                System.out.println(retrieveResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof SubmitIndexAddDocumentsJobResponse submitIndexAddDocumentsJobResponse) {
            if (!Objects.equals(submitIndexAddDocumentsJobResponse.getBody().getStatus(), "200") || !submitIndexAddDocumentsJobResponse.getBody().getSuccess()) {
                System.out.println(submitIndexAddDocumentsJobResponse.getBody().getCode());
                System.out.println(submitIndexAddDocumentsJobResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof ListIndexDocumentsResponse listIndexDocumentsResponse) {
            if (!Objects.equals(listIndexDocumentsResponse.getBody().getStatus(), "200") || !listIndexDocumentsResponse.getBody().getSuccess()) {
                System.out.println(listIndexDocumentsResponse.getBody().getCode());
                System.out.println(listIndexDocumentsResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof ListIndicesResponse listIndicesResponse) {
            if (!Objects.equals(listIndicesResponse.getBody().getStatus(), "200") || !listIndicesResponse.getBody().getSuccess()) {
                System.out.println(listIndicesResponse.getBody().getCode());
                System.out.println(listIndicesResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DeleteIndexResponse deleteIndexResponse) {
            if (!Objects.equals(deleteIndexResponse.getBody().getStatus(), "200") || !deleteIndexResponse.getBody().getSuccess()) {
                System.out.println(deleteIndexResponse.getBody().getCode());
                System.out.println(deleteIndexResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DeleteIndexDocumentResponse deleteIndexDocumentResponse) {
            if (!Objects.equals(deleteIndexDocumentResponse.getBody().getStatus(), "200") || !deleteIndexDocumentResponse.getBody().getSuccess()) {
                System.out.println(deleteIndexDocumentResponse.getBody().getCode());
                System.out.println(deleteIndexDocumentResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        if (response instanceof DeleteCategoryResponse deleteCategoryResponse) {
            if (!Objects.equals(deleteCategoryResponse.getBody().getStatus(), "200") || !deleteCategoryResponse.getBody().getSuccess()) {
                System.out.println(deleteCategoryResponse.getBody().getCode());
                System.out.println(deleteCategoryResponse.getBody().getMessage());
                return false;
            }
            return true;
        }
        return false;
    }

    public static String getCategoryIdByPath(String path) throws Exception {
        ListCategoryServiceImpl listCategoryService = new ListCategoryServiceImpl();
        AddCategoryServiceImpl addCategoryService = new AddCategoryServiceImpl();
        String workspaceId = BailianConfig.workspaceId;
        com.aliyun.bailian20231229.Client client = BailianConfig.createBailianClient();
        List<String> names = BailianFileTools.splitPath(path);
        String className = names.get(0);
        String parentCategoryId = listCategoryService.getCategoryIdByName(client, workspaceId, "UNSTRUCTURED", className);
        System.out.println(parentCategoryId);
        List<String> subNames = names.subList(1, names.size());
        System.out.println(subNames);
        for (String name : subNames) {
            String categoryId = listCategoryService.getCategoryIdByName(client, workspaceId, "UNSTRUCTURED", parentCategoryId, name);
            System.out.println(categoryId);
            if (categoryId == null) {
                AddCategoryResponse response = addCategoryService.addCategory(client, workspaceId, name, "UNSTRUCTURED", parentCategoryId);
                if (!BailianFileTools.checkResponse(response)){
                    return "添加类目失败";
                }
                parentCategoryId = response.getBody().getData().getCategoryId();
            } else {
                parentCategoryId = categoryId;
            }
        }
        return parentCategoryId;
    }

    public static String getIndexIdByName(ListIndicesResponse response, String name) throws Exception {
        AtomicReference<String> indexId = new AtomicReference<>(null);
        response.getBody().getData().getIndices().forEach(index -> {
            if (index.getName().equals(name)) {
                try {
                    System.out.println(index.getId());
                    indexId.set(index.getId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return indexId.get();
    }

    public static String getFileIdByName(ListFileResponse response, String name){
        AtomicReference<String> fileId = new AtomicReference<>(null);
        response.getBody().getData().getFileList().forEach(file -> {
            if (Objects.equals(file.getFileName(), name)){
                try {
                    fileId.set(file.getFileId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return fileId.get();
    }

    public static List<String> getAllFileIds(ListFileResponse response) {
        List<String> fileIds = new ArrayList<>();
        response.getBody().getData().getFileList().forEach(file -> {
            try {
                fileIds.add(file.getFileId());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return fileIds;
    }
}
